﻿//////////////////////////////////////
// editor: HJD   2015-8-15          //
//                                  //
//////////////////////////////////////

(function (icamera) {
    var default_option = {
        videoName: "myVideo",
        quality:100,                        //获取图像的质量
        isDisplaytoOutput:false,            //是否输出到canvas
        outputCanvas: "outputCanvas",       //输出canvas标签的名字
        outputInternal: 0.05,               //输出间隔时间
        isMotionDetection:false,            //是否开启运动检测
        motionDetectionInternal:0.1,        //运动检测间隔时间
        onInitSuccess: function () {
            console.log("onInitSuccess");
        },
        onInitError: function (errorMeg) {
            console.log("onInitError:" + errorMeg);
        },
        onOutput: function (imageData) {
        },
        onDetected: function (imageData) {
        },
        onError:function(errorMsg)
        {}
    }

    icamera.jqCamera = {
        option: default_option,
        init: function (option) {
            this.option = $.extend({}, this.option, option);
            //修正参数
            this.option.quality = parseInt(this.option.quality);
            if (this.option.quality > 100 || this.option.quality<0)
            {
                this.option.quality = 100;
            }
            //init Camera
            var video = document.getElementById(this.option.videoName);
            if (video == undefined) {
                this.option.onInitError("lable video:" + this.option.videoName + " undefined!");
                return;
            }
            var videoObj = {
                video: true,
            };
            // Put video listeners into place
            if (navigator.getUserMedia) { // Standard
                navigator.getUserMedia(videoObj, function (stream) {
                    video.src = stream;
                    video.play();
                }, this.option.onInitError);
            } else if (navigator.webkitGetUserMedia) { // WebKit-prefixed
                navigator.webkitGetUserMedia(videoObj, function (stream) {
                    video.src = window.URL.createObjectURL(stream);
                    video.play();
                }, this.option.onInitError);
            } else if (navigator.mozGetUserMedia) { // WebKit-prefixed
                navigator.mozGetUserMedia(videoObj, function (stream) {
                    video.src = window.URL.createObjectURL(stream);
                    video.play();
                }, this.option.onInitError);
            }
            this.option.onInitSuccess();
            return;
        },
        getCurrentImage: function () {
            var currentVideo = document.getElementById(this.option.videoName);
            var width = currentVideo.videoWidth;
            var height = currentVideo.videoHeight;
            var canvasCurrent = document.createElement('canvas');
            var contextSource = canvasCurrent.getContext("2d");
            contextSource.drawImage(currentVideo, 0, 0, width, height);
            var imageBase64 = canvasCurrent.toDataURL('image/jpeg', this.option.quality);
            return imageBase64;
        },
        getCurrentImageData: function () {
            var currentVideo = document.getElementById(this.option.videoName);
            var width = currentVideo.videoWidth;
            var height = currentVideo.videoHeight;
            var canvasCurrent = document.createElement('canvas');
            var contextSource = canvasCurrent.getContext("2d");
            contextSource.drawImage(currentVideo, 0, 0, width, height);
            var sourceData = contextSource.getImageData(0, 0, width, height);
            return sourceData;
        },
        setOutPut: function (outputCanvas, outputInternal) {
            this.option.isDisplaytoOutput = true;
            this.option.outputCanvas = outputCanvas;
            this.option.outputInternal = outputInternal;
        },
        startOutput: function () {
            if (this.option.isDisplaytoOutput == false)
            {
                this.option.onError("set display output first!");
                return;
            }
            displayVideo = document.getElementById(this.option.videoName);
            displayCanvas = document.getElementById(this.option.outputCanvas);
            displayContent = displayCanvas.getContext("2d");
            display();
        },
        setMotionDetection: function (motionDetectionInternal) {
            this.option.isMotionDetection = true;
            this.option.motionDetectionInternal = motionDetectionInternal;
        },
        startDetection: function () {
            if (this.option.isMotionDetection == false) {
                this.option.onError("set motion detection first!");
                return;
            }
            displayVideo = document.getElementById(this.option.videoName);
            motionDetection();
        }
    }

    //private functions
    var displayVideo;
    var displayCanvas;
    var displayContent;
    var lastImageData;
    function display()
    {
        var width = displayVideo.videoWidth;
        var height = displayVideo.videoHeight;
        if (width > 0 && height > 0) {
            displayContent.drawImage(displayVideo, 0, 0, width, height);
            var displayImage = displayContent.getImageData(0, 0, width, height);
            icamera.jqCamera.option.onOutput(displayImage.data);
        }

        setTimeout(display, icamera.jqCamera.option.outputInternal);
    }

    function motionDetection() {
        var width = displayVideo.videoWidth;
        var height = displayVideo.videoHeight;
        if (width > 0 && height > 0) {
            var canvasSource = document.createElement('canvas');
            var contextSource = canvasSource.getContext('2d');
            contextSource.drawImage(displayVideo, 0, 0, width, height);
            var sourceData = contextSource.getImageData(0, 0, width, height);
            if (!lastImageData) lastImageData = contextSource.getImageData(0, 0, width, height);

            var imgDiff = imageDifference(sourceData.data, lastImageData.data);
            if (imgDiff > 10000) {
                icamera.jqCamera.option.onDetected(sourceData.data);
            }
            lastImageData = sourceData;
        }
        setTimeout(motionDetection, icamera.jqCamera.option.motionDetectionInternal);
    }

    /////////////////////
    //判断是否为PC端
    function IsPC() {
        var userAgentInfo = navigator.userAgent;
        var Agents = ["Android", "iPhone",
                    "SymbianOS", "Windows Phone",
                    "iPad", "iPod", "windows ce", "windows mobile"];
        var flag = true;
        for (var v = 0; v < Agents.length; v++) {
            if (userAgentInfo.indexOf(Agents[v]) > 0) {
                flag = false;
                break;
            }
        }
        return flag;
    }

    function differenceAccuracy(target, data1, data2) {
        if (data1.length != data2.length) return null;
        var i = 0;
        while (i < (data1.length * 0.25)) {
            var average1 = (data1[4 * i] + data1[4 * i + 1] + data1[4 * i + 2]) / 3;
            var average2 = (data2[4 * i] + data2[4 * i + 1] + data2[4 * i + 2]) / 3;
            var diff = threshold(fastAbs(average1 - average2));
            target[4 * i] = diff;
            target[4 * i + 1] = diff;
            target[4 * i + 2] = diff;
            target[4 * i + 3] = 0xFF;
            ++i;
        }
    }

    function imageDifference(data1, data2) {
        if (data1.length != data2.length) return 0;
        var i = 0;
        var diffRate = 0;
        while (i < (data1.length * 0.25)) {
            var average1 = (data1[4 * i] + data1[4 * i + 1] + data1[4 * i + 2]) / 3;
            var average2 = (data2[4 * i] + data2[4 * i + 1] + data2[4 * i + 2]) / 3;
            var diff = threshold(fastAbs(average1 - average2));
            if (diff > 0) {
                diffRate++;
            }
            ++i;
        }
        return diffRate;
    }

    function fastAbs(value) {
        // equivalent to Math.abs();
        return (value ^ (value >> 31)) - (value >> 31);
    }

    function threshold(value) {
        return (value > 0x15) ? 0xFF : 0;
    }
})(window)